package main

import (
	"fmt"
	"time"
)

func A() (string, string, string) {
	time.Sleep(1 * time.Second)
	return "X0", "Y0", "Z0"
}

func B1(x *string) {
	time.Sleep(1 * time.Second)
	*x = "X"
}

func B2(y *string) {
	time.Sleep(2 * time.Second)
	*y = "Y"
}

func B3(z *string) {
	time.Sleep(3 * time.Second)
	*z = "Z"
}

func C(x, y, z string) string {
	time.Sleep(1 * time.Second)
	return x + y + z
}

func elapse() func() {
	now := time.Now()
	return func() {
		fmt.Printf("elapse:%.3f ms\n", 1000*time.Since(now).Seconds())
	}
}

func main() {
	defer elapse()()
	x, y, z := A()

	wait := make(chan struct{}, 3)
	go func() {
		B1(&x)
		wait <- struct{}{}
	}()
	go func() {
		B2(&y)
		wait <- struct{}{}
	}()
	go func() {
		B3(&z)
		wait <- struct{}{}
	}()

	for i := 0; i < 3; i++ {
		<-wait
	}
	p := C(x, y, z)
	fmt.Printf("produce:%s\n", p)
}
